home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.sources.misc
- From: Bill Norcott <norcott@databs.enet.dec.com>
- Subject: v20i019: iozone - sequential file I/O benchmark for UNIX, VMS & DOS, Part01/01
- Message-ID: <1991May24.212531.1174@sparky.IMD.Sterling.COM>
- X-Md4-Signature: 98e48bc9b64c65bf38abbed9cb6efee4
- Date: Fri, 24 May 1991 21:25:31 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: Bill Norcott <norcott@databs.enet.dec.com>
- Posting-number: Volume 20, Issue 19
- Archive-name: iozone/part01
- Supersedes: iozone: Volume 17, Issue 65
-
- IOzone is an I/O benchmark which I have written. It is a performance
- test of sequential file I/O. IOzone calculates the speed at which
- your system reads and writes files, and prints the rate in bytes per
- second. This is a portable benchmark, and has been tested on
- VAX/VMS, MS-DOS, AIX, SCO UNIX, SUNOS, ULTRIX, etc. I would appreciate
- feedback on any changes needed to make it compile on Hewlett Packard,
- Apple, Interactive Unix, etc -- systems not already on my list.
-
- Attached is IOzone V1.08. This version includes auto test mode
- which performs a series of tests on file sizes from 1-16 MB and
- record lengths from 512 to 8192 bytes. It is invoked by the
- typing: iozone auto from the the shell. This version also
- fixes auto mode when compiled with Borland Turbo C on MS-DOS,
- and lets you compile IOzone on SUNOS without having to use
- -Dnolimits (the source code now compiles on SUNOS with the
- simple cc -o iozone iozone.c).
-
- Bill Norcott
-
- ------------------------ CUT HERE -------------------------
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: iozone.c
- # Wrapped by kent@sparky on Fri May 24 15:40:33 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive."'
- if test -f 'iozone.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'iozone.c'\"
- else
- echo shar: Extracting \"'iozone.c'\" \(14433 characters\)
- sed "s/^X//" >'iozone.c' <<'END_OF_FILE'
- X/*
- X* "IO Zone" Benchmark Program
- X*
- X* Author: Bill Norcott (Bill.Norcott@nuo.mts.dec.com)
- X* 4 Dunlap Drive
- X* Nashua, NH 03060
- X*
- X* "Copyright 1991, William D. Norcott
- X* License to freely use and distribute this software is hereby granted
- X* by the author, subject to the condition that this copyright notice
- X* remains intact. The author retains the exclusive right to publish
- X* derivative works based on this work, including, but not limited,
- X* to revised versions of this work"
- X*
- X* "This test writes a 4 MEGABYTE sequential file in 512 byte chunks, then
- X* rewinds it and reads it back. [The size of the file should be
- X* big enough to factor out the effect of any disk cache.]
- X*
- X* The file is written (filling any cache buffers), and then read. If the
- X* cache is >= 4 MB, then most if not all the reads will be satisfied from
- X* the cache. However, if it is less than or equal to 2 MB, then NONE of
- X* the reads will be satisfied from the cache. This is becase after the
- X* file is written, a 2 MB cache will contain the upper 2 MB of the test
- X* file, but we will start reading from the beginning of the file (data
- X* which is no longer in the cache)
- X*
- X* In order for this to be a fair test, the length of the test file must
- X* be AT LEAST 2X the amount of disk cache memory for your system. If
- X* not, you are really testing the speed at which your CPU can read blocks
- X* out of the cache (not a fair test)
- X*
- X* IOZONE does NOT test the raw I/O speed of your disk or system. It
- X* tests the speed of sequential I/O to actual files. Therefore, this
- X* measurement factors in the efficiency of you machines file system,
- X* operating system, C compiler, and C runtime library. It produces a
- X* measurement which is the number of bytes per second that your system
- X* can read or write to a file.
- X*
- X* For V1.06, IOZONE adds the "auto test" feature. This is activated
- X* by the command: 'iozone auto' . The auto test runs IOZONE repeatedly
- X* using record sizes from 512 to 8192 bytes, and file sizes from 1 to 16
- X* megabytes. It creates a table of results.
- X*
- X* For V1.06, IOZONE lets you specify the number of file system sizes and
- X* record lengths to test when using auto mode. Define the constants
- X* MEGABYTES_ITER_LIMIT and RECLEN_ITER_LIMIT as seen below
- X*
- X* This program has been ported and tested on the following computer
- X* operating systems:
- X*
- X* AIX Version 3 release 1 (compile: cc -Dunix -o iozone iozone.c)
- X* MS-DOS 3.3 (Turbo C, Turbo C++, Microsoft C)
- X* OSF/1
- X* SCO Unix System V release 3.2 version 2
- X* SUNOS 4.0.3, SUNOS 4.1.1
- X* Ultrix V4.1
- X* VAX/VMS V5.4 **
- X* XENIX 3.2
- X*
- X* ** for VMS, define iozone as a foreign command via this DCL command:
- X*
- X* $IOZONE :== $SYS$DISK:[]IOZONE.EXE
- X*
- X* this lets you pass the command line arguments to IOZONE
- X*
- X* Acknowledgements to the following persons for their feedback on IOzone:
- X*
- X* Andy Puchrik, Michael D. Lawler, Krishna E. Bera, Sam Drake, John H. Hartman,
- X* Ted Lyszczarz, Bill Metzenthen
- X*
- X* --- MODIFICATION HISTORY:
- X*
- X* 3/7/91 William D. Norcott (Bill.Norcott@nuo.mts.dec.com)
- X* created
- X*
- X* 3/22/91 Bill Norcott tested on OSF/1 ... it works
- X*
- X* 3/24/91 Bill Norcott V1.02 -- use calloc in TURBOC to
- X* fix bug with their malloc
- X*
- X* 3/25/91 Bill Norcott V1.03 -- add ifdef for XENIX
- X*
- X* 3/27/91 Bill Norcott V1.04 -- Includes for SCO UNIX
- X*
- X* 4/26/91 Bill Norcott V1.05 -- support AIX and SUNos, check
- X* length of read() and write()
- X* 4/26/91 Bill Norcott V1.06 -- tabulate results of a series
- X* of tests
- X* 5/17/91 Bill Norcott V1.07 -- use time() for VMS
- X* 5/20/91 Bill Norcott V1.08 -- use %ld for Turbo C and
- X* use #ifdef sun to bypass
- X* inclusion of limits.h
- X*/
- X
- X/******************************************************************
- X
- X INCLUDE FILES (system-dependent)
- X
- X******************************************************************/
- X#ifdef __MSDOS__ /* Turbo C define this way for PCs... */
- X#define MSDOS /* Microsoft C defines this */
- X#endif
- X/* VMS and MS-DOS both have ANSI C compilers and use rand()/srand() */
- X#ifdef VMS_POSIX
- X#undef VMS
- X#define ANSI_RANDOM 1
- X#endif
- X#ifdef MSDOS
- X#define ANSI_RANDOM 1
- X#endif
- X
- X/* incl definitions of O_* flags for XENIX */
- X#ifdef M_XENIX
- X#include <fcntl.h>
- X#endif
- X/* SCO Unix System V */
- X#ifdef M_UNIX
- X#include <sys/types.h>
- X#include <sys/fcntl.h>
- X#endif
- X
- X#if defined(VMS)
- X#define ANSI_RANDOM 1
- X#include <math.h>
- X#include <unixio.h>
- X#include <ssdef.h>
- X#include <file.h>
- X#include <time.h>
- X
- X#elif defined(MSDOS)
- X#include <fcntl.h>
- X#include <time.h>
- X#elif defined(unix)
- X#include <sys/file.h>
- X#ifndef NULL
- X#define NULL 0
- X#endif
- X/*
- Xdefine nolimits if your system has no limits.h. Sun's don't but I
- Xtake care of this explicitly beginning with V1.08 of IOzone.
- X*/
- X#ifdef sun
- X#define nolimits
- X#define BSDtime
- X#endif
- X#ifndef nolimits
- X#include <limits.h>
- X#endif
- X#endif
- X/* for systems with System V-style time, define SysVtime */
- X#ifdef M_SYSV
- X#define SysVtime
- X#endif
- X
- X#ifdef SysVtime
- X#include <sys/times.h>
- X#include <sys/param.h>
- X#ifndef CLK_TCK
- X#define CLK_TCK HZ
- X#endif
- X#endif
- X/* for systems with BSD style time, define BSDtime */
- X#ifdef bsd4_2
- X#define BSDtime
- X#endif
- X#ifdef BSDtime
- X#include <sys/time.h>
- X#endif
- X
- X
- X/******************************************************************
- X
- X DEFINED CONSTANTS
- X
- X******************************************************************/
- X#define MEGABYTES 1 /* number of megabytes in file */
- X#define RECLEN 512 /* number of bytes in a record */
- X#define FILESIZE (MEGABYTES*1024*1024) /*size of file in bytes*/
- X#define NUMRECS FILESIZE/RECLEN /* number of records */
- X#define MAXBUFFERSIZE 16*1024 /*maximum buffer size*/
- X#define MINBUFFERSIZE 128
- X#define TOOFAST 10
- X#define USAGE "\tUsage:\tiozone [megabytes] [record_length_in_bytes] \
- X[[path]filename]\n\n"
- X#define THISVERSION "V1.08"
- X
- X/* Define only one of the following two.*/
- X/*#define NOTIME define if no time function in library*/
- X#define TIME /*Use time(2)function*/
- X#define MAXNAMESIZE 1000 /* max # of characters in filename */
- X#define CONTROL_STRING1 "\t%-8ld%-8ld%-20ld%-20ld\n"
- X#define CONTROL_STRING2 "\t%-8s%-8s%-20s%-20s\n"
- X/*
- X For 'auto mode', these defines determine the number of iterations
- X to perform for both the file size and the record length.
- X I.e., if MEGABYTES_ITER_LIMIT = 5 use 1, 2, 4, 8 & 16 megabyte files
- X if RECLEN_ITER_LIMIT = 5 use 512, 1024, 2048, 4096 & 8192 byte records
- X*/
- X#define MEGABYTES_ITER_LIMIT 5
- X#define RECLEN_ITER_LIMIT 5
- X
- X/******************************************************************
- X
- X FUNCTION DECLARATIONS
- X
- X******************************************************************/
- Xvoid auto_test(); /* perform automatic test series */
- Xstatic double time_so_far(); /* time since start of program */
- X/******************************************************************
- X
- X GLOBAL VARIABLES
- X
- X******************************************************************/
- Xint auto_mode;
- X
- X/******************************************************************
- X
- X MAIN -- entry point
- X
- X******************************************************************/
- Xmain(argc,argv)
- X int argc;
- X char *argv[];
- X{
- Xint fd;
- Xchar filename [MAXNAMESIZE]; /* name of temporary file */
- Xchar *default_filename="iozone.tmp"; /*default name of temporary file*/
- X
- X#ifdef MSDOS
- Xchar *buffer;
- X#else
- Xchar buffer [MAXBUFFERSIZE]; /*a temporary data buffer*/
- X#endif
- Xint i, status;
- Xunsigned long megabytes = MEGABYTES, goodmegs;
- Xunsigned long reclen = RECLEN, goodrecl;
- Xunsigned long filesize = FILESIZE;
- Xunsigned long numrecs = NUMRECS;
- Xunsigned long filebytes;
- Xunsigned long readrate, writerate;
- X#ifdef TIME
- X double starttime1, starttime2;
- X double writetime, readtime;
- X double totaltime;
- X
- X#endif
- X
- X#ifdef MSDOS
- X buffer = (char *) calloc(1, MAXBUFFERSIZE);
- X#endif
- X
- X if (!auto_mode)
- X {
- X printf("\n\tIOZONE: Performance Test of Sequential File I/O -- %s\n",
- X THISVERSION);
- X printf("\t\tBy Bill Norcott\n\n");
- X }
- X strcpy(filename,default_filename);
- X switch (argc) {
- X case 1: /* no args, take all defaults */
- X printf(USAGE);
- X break;
- X case 2: /* <megabytes|filename> */
- X i = atoi(argv[1]); if (i) {
- X megabytes = i;
- X } else {
- X/*
- X'Auto mode' will be enabled if the first command line argument is
- Xthe word 'auto'. This will trigger a series of tests
- X*/
- X if ( (strcmp(argv[1], "auto") == 0) ||
- X (strcmp(argv[1], "AUTO") == 0) )
- X {
- X auto_mode = 1;
- X auto_test();
- X printf("Completed series of tests\n");
- X exit(0);
- X } else {
- X auto_mode = 0;
- X }
- X strcpy(filename,argv[1]);
- X }
- X break;
- X case 3: /* <megabytes> <reclen|filename> */
- X megabytes = atoi(argv[1]);
- X if (atoi(argv[2])) {
- X reclen = atoi(argv[2]);
- X } else {
- X strcpy(filename,argv[2]);
- X }
- X break;
- X case 4: /* <megabytes> <reclen> <filename> */
- X megabytes = atoi(argv[1]);
- X reclen = atoi(argv[2]);
- X strcpy(filename,argv[3]);
- X break;
- X default:
- X printf(USAGE);
- X exit(1);
- X
- X }
- X if (!auto_mode)
- X {
- X printf("\tSend comments to:\tBill.Norcott@nuo.mts.dec.com\n\n");
- X }
- X filesize = megabytes*1024*1024;
- X numrecs = filesize/reclen;
- X if (reclen > MAXBUFFERSIZE) {
- X printf("Error: Maximum record length is %d bytes\n", MAXBUFFERSIZE);
- X exit(1);
- X }
- X if (reclen < MINBUFFERSIZE) {
- X printf("Error: Minimum record length is %d bytes\n", MINBUFFERSIZE);
- X exit(1);
- X }
- X if (!auto_mode)
- X {
- X printf("\tIOZONE writes a %ld Megabyte sequential file consisting of\n",
- X megabytes);
- X printf("\t%ld records which are each %ld bytes in length.\n",
- X numrecs, reclen);
- X printf("\tIt then reads the file. It prints the bytes-per-second\n");
- X printf("\trate at which the computer can read and write files.\n\n");
- X printf("\nWriting the %ld Megabyte file, '%s'...", megabytes, filename);
- X }
- X if((fd = creat(filename, 0640))<0){
- X printf("Cannot create temporary file\n");
- X exit(1);
- X }
- X#ifdef TIME
- X starttime1 = time_so_far();
- X#endif
- X for(i=0; i<numrecs; i++){
- X#ifndef DEBUG_ME
- X if(write(fd, buffer, (unsigned) reclen) != reclen)
- X {
- X printf("Error writing block %d\n", i);
- X exit(1);
- X }
- X#endif
- X }
- X
- X#ifdef TIME
- X writetime = time_so_far() - starttime1;
- X if (!auto_mode)
- X {
- X printf("%f seconds", writetime);
- X }
- X#endif
- X close(fd);
- X#if defined (VMS)
- X if((fd = open(filename, O_RDONLY, 0640))<0){
- X printf("Cannot open temporary file for read\n");
- X exit(1);
- X }
- X#elif defined(MSDOS)
- X if((fd = open(filename, O_RDONLY, 0640))<0){
- X printf("Cannot open temporary file for read\n");
- X exit(1);
- X }
- X#else
- X if((fd = open(filename, O_RDONLY))<0){
- X printf("Cannot open temporary file for read\n");
- X exit(1);
- X }
- X#endif
- X
- X
- X /*start timing*/
- X#if defined(NOTIME)
- X printf("start timing\n");
- X#endif
- X if (!auto_mode)
- X {
- X printf("\nReading the file...");
- X }
- X starttime2 = time_so_far();
- X for(i=0; i<numrecs; i++) {
- X#ifndef DEBUG_ME
- X if(read(fd, buffer, (unsigned) reclen) != reclen)
- X {
- X printf("Error reading block %d\n", i);
- X exit(1);
- X }
- X#endif
- X }
- X#ifdef NOTIME
- X printf("stop timing\n");
- X#endif
- X#ifdef TIME
- X readtime = time_so_far() - starttime2;
- X if (!auto_mode)
- X {
- X printf("%f seconds\n", readtime);
- X }
- X#ifdef DEBUG_ME
- X readtime = 1;
- X writetime = 1;
- X#endif
- X if(readtime!=0)
- X {
- X filebytes = numrecs*reclen;
- X readrate = (unsigned long) ((double) filebytes / readtime);
- X writerate = (unsigned long) ((double) filebytes / writetime);
- X if (auto_mode)
- X {
- X printf(CONTROL_STRING1,
- X megabytes,
- X reclen,
- X writerate,
- X readrate);
- X
- X } else {
- X printf("\nIOZONE performance measurements:\n");
- X printf("\t%ld bytes/second for writing the file\n", writerate);
- X printf("\t%ld bytes/second for reading the file\n", readrate);
- X totaltime = readtime + writetime;
- X if (totaltime < TOOFAST)
- X {
- X goodmegs = (TOOFAST/totaltime)*2*megabytes;
- X printf("\nThe test completed too quickly to give a good result\n");
- X printf("You will get a more precise measure of this machine's\n");
- X printf("performance by re-running IOZONE using the command:\n");
- X printf("\n\tiozone %ld ", goodmegs);
- X printf("\t(i.e., file size = %ld megabytes)\n", goodmegs);
- X }
- X }
- X } else {
- X goodrecl = reclen/2;
- X printf("\nI/O error during read. Try again with the command:\n");
- X printf("\n\tiozone %ld %ld ", megabytes, goodrecl);
- X printf("\t(i.e. record size = %ld bytes)\n", goodrecl);
- X }
- X#endif
- X close(fd);
- X#ifndef VMS
- X unlink(filename); /* delete the file */
- X /*stop timer*/
- X#endif
- X#ifdef MSDOS
- X free(buffer); /* deallocate the memory */
- X#endif
- X#ifdef VMS
- Xreturn SS$_NORMAL;
- X#else
- Xreturn 0;
- X#endif
- X}
- X/******************************************************************
- X
- X AUTO TEST -- perform series of tests and tabulate results
- X
- X******************************************************************/
- Xvoid auto_test()
- X{
- X int megsi, recszi;
- X char megs[10];
- X char recsz[10];
- X int i,j;
- X int argc = 3;
- X char *argv[3];
- X
- X printf(CONTROL_STRING2,
- X "MB",
- X "reclen",
- X "bytes/sec written",
- X "bytes/sec read");
- X argv[0] = "IOzone auto-test";
- X argv[1] = megs;
- X argv[2] = recsz;
- X/*
- XStart with file size of 1 megabyte and repeat the test MEGABYTES_ITER_LIMIT
- Xtimes. Each time we run, the file size is doubled
- X*/
- X for(i=0,megsi=1;i<MEGABYTES_ITER_LIMIT;i++,megsi*=2)
- X {
- X sprintf(megs, "%d", megsi);
- X/*
- XStart with record size of 512 bytes and repeat the test RECLEN_ITER_LIMIT
- Xtimes. Each time we run, the record size is doubled
- X*/
- X for (j=0,recszi=512;j<RECLEN_ITER_LIMIT;j++,recszi*=2)
- X {
- X sprintf(recsz, "%d", recszi);
- X main(argc, argv);
- X }
- X }
- X}
- X
- Xstatic double
- Xtime_so_far()
- X{
- X#if defined(VMS)
- X/*
- X* 5/17/91 Bill Norcott V1.07 -- use time() for VMS
- XThe times() function in VMS returns proc & user CPU time in 10-millisecond
- Xticks. Instead, use time() which lacks the precision but gives clock
- Xtime in seconds.
- X*/
- X
- X return (double) time(NULL);
- X
- X#elif defined(SysVtime)
- X int val;
- X struct tms tms;
- X
- X if ((val = times(&tms)) == -1)
- X perror("times");
- X
- X return ((double) val) / ((double) CLK_TCK);
- X#elif defined(MSDOS)
- X return ((double) clock()) / ((double) CLK_TCK);
- X#else
- X struct timeval tp;
- X
- X if (gettimeofday(&tp, (struct timezone *) NULL) == -1)
- X perror("gettimeofday");
- X return ((double) (tp.tv_sec)) +
- X (((double) tp.tv_usec) / 1000000.0);
- X#endif
- X}
- END_OF_FILE
- if test 14433 -ne `wc -c <'iozone.c'`; then
- echo shar: \"'iozone.c'\" unpacked with wrong size!
- fi
- # end of 'iozone.c'
- fi
- echo shar: End of archive.
- exit 0
- exit 0 # Just in case...
- --
- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
- Sterling Software, IMD UUCP: uunet!sparky!kent
- Phone: (402) 291-8300 FAX: (402) 291-4362
- Please send comp.sources.misc-related mail to kent@uunet.uu.net.
-